package com.fecean.aabbc.commons.easy;

import org.jetbrains.annotations.Nullable;

import java.util.Collection;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

/**
 * 验证类
 *
 * @author chenfenghai
 * @date 2019-12-11 15:46
 * @blame Android Team
 */
public class EasyValidator {

    // Constructor.
    /**
     * private Constructor.
     */
    public EasyValidator(){}

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 是null值
     *
     * <pre>
     * Validator.isNull(null)      = true
     * Validator.isNull("")        = false
     * Validator.isNull(" ")       = false
     * Validator.isNull("bob")     = false
     * Validator.isNull("  bob  ") = false
     * </pre>
     *
     * @param <T> the object type
     * @param object the object to check
     * @return boolean the validated result true or false
     */
    public static <T> boolean isNull(@Nullable final T object){
        return object == null;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 不是null值
     *
     * <pre>
     * Validator.notNull(null)      = false
     * Validator.notNull("")        = true
     * Validator.notNull(" ")       = true
     * Validator.notNull("bob")     = true
     * Validator.notNull("  bob  ") = true
     * </pre>
     *
     * @param <T> the object type
     * @param object the object to check
     * @return boolean the validated result true or false
     */
    public static <T> boolean notNull(@Nullable final T object){
        return object != null;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 是空值
     *
     * <pre>
     * Validator.isEmpty(null)      = true
     * Validator.isEmpty("")        = true
     * Validator.isEmpty(" ")       = false
     * Validator.isEmpty("bob")     = false
     * Validator.isEmpty("  bob  ") = false
     * </pre>
     *
     * @param <T> the object type
     * @param object the object to check
     * @return boolean the validated result true or false
     */
    public static <T> boolean isEmpty(@Nullable final T object){
        return object == null || String.valueOf(object).isEmpty();
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 是空值
     * @param <T> the object type
     * @param chars the object to check
     * @return boolean the validated result true or false
     */
    public static <T extends CharSequence> boolean isEmpty(@Nullable final T chars){
        return chars == null || chars.length() == 0;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 是空值
     * @param <T> the object type
     * @param array the object to check
     * @return boolean the validated result true or false
     */
    public static <T> boolean isEmpty(@Nullable final T[] array){
        System.out.println("public static <T> boolean isEmpty(final T[] array)");
        return array == null || array.length == 0;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 是空值
     * @param <T> the object type
     * @param collection the object to check
     * @return boolean the validated result true or false
     */
    public static <T extends Collection<?>> boolean isEmpty(@Nullable final T collection){
        return collection == null || collection.isEmpty();
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 是空值
     * @param <T> the object type
     * @param map the object to check
     * @return boolean the validated result true or false
     */
    public static <T extends Map<?, ?>> boolean isEmpty(@Nullable final T map){
        return map == null || map.isEmpty();
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 不是空值
     *
     * <pre>
     * Validator.isEmpty(null)      = false
     * Validator.isEmpty("")        = false
     * Validator.isEmpty(" ")       = true
     * Validator.isEmpty("bob")     = true
     * Validator.isEmpty("  bob  ") = true
     * </pre>
     *
     * @param <T> the object type
     * @param object the object to check
     * @return boolean the validated result true or false
     */
    public static <T> boolean notEmpty(@Nullable final T object){
        return !isEmpty(object);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 不是空值
     * @param <T> the object type
     * @param chars the object to check
     * @return boolean the validated result true or false
     */
    public static <T extends CharSequence> boolean notEmpty(@Nullable final T chars){
        return !isEmpty(chars);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 不是空值
     * @param <T> the object type
     * @param array the object to check
     * @return boolean the validated result true or false
     */
    public static <T> boolean notEmpty(@Nullable final T[] array){
        return !isEmpty(array);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 不是空值
     * @param <T> the object type
     * @param collection the object to check
     * @return boolean the validated result true or false
     */
    public static <T extends Collection<?>> boolean notEmpty(@Nullable final T collection){
        return !isEmpty(collection);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 不是空值
     * @param <T> the object type
     * @param map the object to check
     * @return boolean the validated result true or false
     */
    public static <T extends Map<?, ?>> boolean notEmpty(@Nullable final T map){
        return !isEmpty(map);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 是空值
     *
     * <pre>
     * Validator.isBlank(null)      = true
     * Validator.isBlank("")        = true
     * Validator.isBlank(" ")       = true
     * Validator.isBlank("bob")     = false
     * Validator.isBlank("  bob  ") = false
     * </pre>
     *
     * @param <T> the object type
     * @param chars the object to check
     * @return boolean the validated result true or false
     */
    public static <T extends CharSequence> boolean isBlank(@Nullable final T chars){
        int strLen;
        if (chars == null || (strLen = chars.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(chars.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 是空值
     *
     * <pre>
     * Validator.isBlank(null)      = true
     * Validator.isBlank("")        = true
     * Validator.isBlank(" ")       = true
     * Validator.isBlank("bob")     = false
     * Validator.isBlank("  bob  ") = false
     * </pre>
     *
     * @param <T> the object type
     * @param object the object to check
     * @return boolean the validated result true or false
     */
    public static <T> boolean isBlank(@Nullable final T object){
        return object == null || isBlank(object.toString());
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 不是空值
     *
     * <pre>
     * Validator.notBlank(null)      = false
     * Validator.notBlank("")        = false
     * Validator.notBlank(" ")       = false
     * Validator.notBlank("bob")     = true
     * Validator.notBlank("  bob  ") = true
     * </pre>
     *
     * @param <T> the object type
     * @param chars the object to check
     * @return boolean the validated result true or false
     */
    public static <T extends CharSequence> boolean notBlank(@Nullable final T chars){
        return !isBlank(chars);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 不是空值
     *
     * <pre>
     * Validator.notBlank(null)      = false
     * Validator.notBlank("")        = false
     * Validator.notBlank(" ")       = false
     * Validator.notBlank("bob")     = true
     * Validator.notBlank("  bob  ") = true
     * </pre>
     *
     * @param <T> the object type
     * @param object the object to check
     * @return boolean the validated result true or false
     */
    public static <T> boolean notBlank(@Nullable final T object){
        return !isBlank(object);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 判断字符串是否日期格式：yyyy-MM-dd
     *
     * <pre>
     * Validator.isDate(null)                   = false
     * Validator.isDate("")                     = false
     * Validator.isDate("2019/10/18")           = false
     * Validator.isDate("2019-10-18 12:12:12")  = false
     * Validator.isDate("2019-10-18")           = true
     * </pre>
     *
     * @param <T> the object type
     * @param chars the chars to check
     * @return boolean the validated result true or false
     * @see EasyDate#isDate(CharSequence)
     */
    public static <T extends CharSequence> boolean isDate(@Nullable final T chars){
        return EasyDate.isDate(chars);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 判断字符串是否日期格式：yyyy-MM-dd
     *
     * <pre>
     * Validator.isDate(null)                   = false
     * Validator.isDate("")                     = false
     * Validator.isDate("2019/10/18")           = false
     * Validator.isDate("2019-10-18 12:12:12")  = false
     * Validator.isDate("2019-10-18")           = true
     * </pre>
     *
     * @param <T> the object type
     * @param object the object to check
     * @return boolean the validated result true or false
     * @see EasyDate#isDate(CharSequence)
     */
    public static <T> boolean isDate(@Nullable final T object){
        return object != null && EasyDate.isDate(String.valueOf(object));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 判断字符串是否日期时间格式：yyyy-MM-dd HH:mm:ss
     *
     * <pre>
     * Validator.isDateTime(null)                   = false
     * Validator.isDateTime("")                     = false
     * Validator.isDateTime("2019/10/18")           = false
     * Validator.isDateTime("2019-10-18 12:12:12")  = true
     * Validator.isDateTime("2019-10-18")           = false
     * </pre>
     *
     * @param <T> the object type
     * @param chars the object to check
     * @return boolean the validated result true or false
     * @see EasyDate#isDateTime(CharSequence)
     */
    public static <T extends CharSequence> boolean isDateTime(@Nullable final T chars){
        return EasyDate.isDateTime(chars);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 判断字符串是否日期时间格式：yyyy-MM-dd HH:mm:ss
     *
     * <pre>
     * Validator.isDateTime(null)                   = false
     * Validator.isDateTime("")                     = false
     * Validator.isDateTime("2019/10/18")           = false
     * Validator.isDateTime("2019-10-18 12:12:12")  = true
     * Validator.isDateTime("2019-10-18")           = false
     * </pre>
     *
     * @param <T> the object type
     * @param object the object to check
     * @return boolean the validated result true or false
     * @see EasyDate#isDateTime(CharSequence)
     */
    public static <T> boolean isDateTime(@Nullable final T object){
        return object != null && EasyDate.isDateTime(String.valueOf(object));
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 判断字符串是否指定日期格式
     *
     * <pre>
     * Validator.isDateTimeFormat(null, "yyyy-MM-dd")                             = false
     * Validator.isDateTimeFormat("", "yyyy-MM-dd")                               = false
     * Validator.isDateTimeFormat("2019/10/18", "yyyy/MM/dd")                     = true
     * Validator.isDateTimeFormat("2019-10-18", "yyyy-MM-dd")                     = true
     * Validator.isDateTimeFormat("20191018", "yyyy-MM-dd")                       = false
     * Validator.isDateTimeFormat("2019-10-18 12:12:12", "yyyy-MM-ddTHH:mm:ss")   = false
     * Validator.isDateTimeFormat("2019-10-18 12:12:12", "yyyy-MM-dd HH:mm:ss")   = true
     * </pre>
     *
     * @param <T> the object type
     * @param chars the object to check
     * @param pattern the datetime format. for example: yyyy-MM-dd HH:mm:ss
     * @return boolean the validated result true or false
     * @see EasyDate#isDateTimeFormat(CharSequence, String)
     */
    public static <T extends CharSequence> boolean isDateTimeFormat(@Nullable final T chars, final String pattern){
        return EasyDate.isDateTimeFormat(chars, pattern);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 判断字符串是否指定日期格式
     *
     * <pre>
     * Validator.isDateTimeFormat(null, "yyyy-MM-dd")                             = false
     * Validator.isDateTimeFormat("", "yyyy-MM-dd")                               = false
     * Validator.isDateTimeFormat("2019/10/18", "yyyy/MM/dd")                     = true
     * Validator.isDateTimeFormat("2019-10-18", "yyyy-MM-dd")                     = true
     * Validator.isDateTimeFormat("20191018", "yyyy-MM-dd")                       = false
     * Validator.isDateTimeFormat("2019-10-18 12:12:12", "yyyy-MM-ddTHH:mm:ss")   = false
     * Validator.isDateTimeFormat("2019-10-18 12:12:12", "yyyy-MM-dd HH:mm:ss")   = true
     * </pre>
     *
     * @param <T> the object type
     * @param object the object to check
     * @param pattern the datetime format. for example: yyyy-MM-dd HH:mm:ss
     * @return boolean the validated result true or false
     * @see EasyDate#isDateTimeFormat(CharSequence, String)
     */
    public static <T> boolean isDateTimeFormat(@Nullable final T object, final String pattern){
        return object != null && EasyDate.isDateTimeFormat(String.valueOf(object), pattern);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 验证正则表达式是否匹配
     * @param regex The expression to be compiled
     * @param chars The character sequence to be matched
     * @return boolean the validated result true or false
     */
    public static <T extends CharSequence> boolean isMatch(@Nullable String regex, @Nullable T chars){
        if(regex == null || chars == null){
            return false;
        }
        try {
            return Pattern.matches(regex, chars);
        }catch (PatternSyntaxException pse){
            return false;
        }
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 验证正则表达式是否匹配
     * @param regex The expression to be compiled
     * @param object The object sequence to be matched
     * @return boolean The validated result true or false
     */
    public static <T> boolean isMatch(@Nullable String regex, @Nullable T object){
        return object != null && isMatch(regex, String.valueOf(object));
    }
}
